.model tiny

.code
org 100h

locals

Start:		
		mov ax, offset Str_2
		push ax		;
		mov ax, offset Str_to_check
		push ax		;
		call Memcmp     ;
		je Stop         ;
		jb Stop         ;
		ja Stop         ;
		
Stop:		mov ax, 4c00h	;
		int 21h		;
		

;===========================================================;
; Calculates string length.                                 ;
;-----------------------------------------------------------;
; Entry: sp[+0] -> string.                                 ;
; Exit: sp[+0] = len. 0ffffh means pointer is bad.         ;
; Destr: SI, AX, CX.                                        ;
;===========================================================;

Strlen		proc		;
		push bp		;
		mov bp, sp	;
		mov si, [bp+4]	;
				
		mov cx, 0ffffh	; cx = -1
		or si, si	;
		jz @@Exit	; check si.
		
		xor al, al	;
		repne scasb	; while ([si++] != al) cx--;
		inc cx		; -1 is extra.
		neg cx		;
		
@@Exit:		pop bp		; we don't want to corrupt bp.
		pop ax		; get ret adress.
		push cx		; push result.
		push ax		; push ret adress.
      		ret		;
		endp		;

;==========================================================
; Copies one string to the adress.
;----------------------------------------------------------
; Entry: sp[+0] -> string.
;	 sp[+2] -> adress to copy to.
; Exit:  None.
; Destr: SI, DI, AX, CX.
;==========================================================

Strcpy		proc		;
                push bp		; we save bp.
                mov bp, sp	;
                mov si, [bp+4]	;
                mov di, [bp+6]	;

                or si, si	;
                jz @@Exit	;
                or di, di	;
                jz @@Exit	; check si & di.

                push si		;
                push di		; save si & di
                push si		; give Strlen() si as an argument.
                call Strlen     ;
                pop cx		; cx = Strlen(si);
                pop di		; Get wastes.
                pop di		; 
                pop si		; load si & di.

@@cpy:          movsb           ;
                loop @@cpy	; for (cx = Strlen(si); cx > 0; cx--) {

@@Exit:         pop bp		;
                ret             ;
		endp            ;
                                                           
;==========================================================
; Stores same values to adress.
;----------------------------------------------------------
; Entry: sp[+0] -> adress.
;	 sp[+2] = length.
;	 sp[+4] = value.
;	 sp[+6] = 0 - use byte; 1 - use word. 
; Exit:  None.
; Destr: SI, DI, AX, BX, CX.
;==========================================================

Setmem		proc            ;
                push bp         ;
                mov bp, sp	;
                mov di, [bp+4]	;
                mov cx, [bp+6]	;
                mov ax, [bp+8]	;
                mov bx, [bp+10]	;

                or di, di	;
                jz @@Exit	; check di.

                or bx, bx	;
                jnz @@store_w	;

@@store_b:      stosb		;
		loop @@store_b	; for (cx = length; cx > 0; cx--) {
		jmp @@Exit	;

@@store_w:	stosw		;
		loop @@store_w	;

@@Exit:         pop bp		;
                ret		;
                endp            ;

;==========================================================
; Compares two areas of memory (by ASCII codes).
;----------------------------------------------------------
; Entry: sp[+0] ->  left_adress.
;	 sp[+2] -> right_adress.              
; Exit:  Changes flags.
; Destr: SI, DI, AX, CX.
;==========================================================

Memcmp		proc		;
		push bp		;
		mov bp, sp	;
		mov si, [bp+4]	;
		mov di, [bp+6]	;
		mov cx, 0ffffh	;
		
		or si, si	;
		jz @@Exit	;
		or di, di	;
		jz @@Exit	;

		push si		;
                push di		; save si & di
                push si		; give Strlen() si as an argument.
                call Strlen     ;
                pop cx		; cx = Strlen(si);
                pop di		; Get wastes.
                pop di		; 
                pop si		; load si & di.

@@cmp:		cmpsb
		jne @@Exit	;	
		loop @@cmp	; there is no difference between si & di if they are equal.
				; and if they aren't, 0 is lesser than anything anyway.
@@Exit:		pop bp		;
                ret		;
                endp		;

;==========================================================

Str_to_check:	db 'Hello, world!', 0, '$'
Str_2:		db 'Hello, world!', 0, '$'

end		Start